package com.apes.scm.masterdata.frame.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.EventUtil;
import com.apes.scm.masterdata.area.model.Area;
import com.apes.scm.masterdata.area.model.BusinessCircle;
import com.apes.scm.masterdata.area.repository.AreaRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.model.Store;
import com.apes.scm.masterdata.frame.repository.BranchRepository;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.frame.repository.StoreDao;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import com.apes.scm.masterdata.party.model.Corporate;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.DepotRepository;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service("storeService")
public class StoreService extends DomainService{
    @Autowired
    private StoreRepository storeRepository;

    @Autowired
    private StoreDao storeDao;

    @Autowired
    PartyRoleRepository partyRoleRepository;

    @Autowired
    BranchRepository branchRepository;
    @Autowired
    DeptRepository deptRepository;
    @Autowired
    LocationRepository locationRepository;
    @Autowired
    DepotRepository depotRepository;
    @Autowired
    SequenceService sequenceService;
    @Autowired
    AreaRepository areaRepository;
    @Autowired
    private EnumerationRepository enumerationRepository;

    public Store save(SimpleRequest request) {
        Store store = request.getO(Store.class);
        setCity(store);
        if (store.getId() == null) {
            store.setId(store.getDept().getId());
        }
        if (Objects.isNull(store.getOutsourcingApproval())) {
            store.setOutsourcingApproval(enumerationRepository.findOne("002305"));
        }
        if (store.getId() != null) {
            if (branchRepository.findOne(store.getId()) != null) {
                throw new RuntimeException("门店【" + store.getId() + "】在系统中已存在。");
            }
        }

        return storeRepository.saveAndFlush(store);
    }

    public void setCity(Store store){
        // 获取注册区县
        Area county = store.getCounty();// 注册地址.区县
        // 获取注册城市编码
        String cityId = county.getParent();
        // 查找注册城市
        Area city = areaRepository.findOne(cityId);
        store.setCity(city); // 注册地址.城市
        // 设置注册城市
        String provinceId = city.getParent();
        Area province = areaRepository.findOne(provinceId);
        store.setProvince(province); //注册地址.省份
    }

    /**
     * 功能：查询
     *
     * @param request
     */
    public Page<Store> findAll(SimpleRequest request) {
        List<Map> filters = request.get("condition");
        return storeRepository.findAll(JpaDsl.toCriteria(filters), PageRequest.of(request.get("page"), request.get("size")));
    }

    /**
     * 功能：查询
     *
     * @param request
     */
    public PageImpl findAllFilter(SimpleRequest request) {
        List<Map> filters = request.get("condition");
        Page<Store> storePage = storeRepository.findAll(JpaDsl.toCriteria(filters), PageRequest.of(request.get("page"), request.get("size")));
        List<Store> storeList = storePage.getContent();
        storeList.stream().forEach(store -> {
            store.setStoreInfo(getStoreInfo(store));
        });
        Pageable pageable = storePage.getPageable();
        return new PageImpl(storeList, pageable,storePage.getTotalElements());
    }

    /**
     * 获取门店附加信息
     * @param store
     * @return
     */
    private JSONObject getStoreInfo(Store store){
        JSONObject storeJson = new JSONObject();
        JSONObject param = new JSONObject();

        Corporate corporate = store.getCompany().getParty().getCorporate();
        String description = corporate.getOperation().getDescription();

        Location location = locationRepository.findLocationByDept(store.getDept().getId()).stream().findFirst().orElse(null);

        param.put("phy_depot_id",location!=null&&location.getPhyDepot()!=null ?location.getPhyDepot().getId():null);
        param.put("ClocationId",location!=null ?location.getId():null);
        param.put("deptId",store.getDept().getId());
        param.put("companyId", store.getCompany().getId());

        JSONArray locationList = storeDao.findLocationByCompany(param);
        JSONArray fnContract = storeDao.findFnContractByCompany(param);
        JSONArray site = storeDao.findFirstByPhyDepotId(param);
        JSONArray groupDept = storeDao.queryPurchasingGroupDept(param);
        JSONArray shippingAddress = storeDao.findByShippingAddress(param);
        JSONArray mainShippingAddress = storeDao.findByMainShippingAddress(param);
        JSONArray dcDistributionRanges = storeDao.findAllByCLocationId(param);
        JSONArray depot = storeDao.findDepotLocationBydept(param);
        JSONArray phyLocation = storeDao.findPhyLocationBydept(param);

        storeJson.put("operation", description);
        storeJson.put("fnContract", stringAppendIdAndName(fnContract,false));
        storeJson.put("location", location);
        storeJson.put("locationDepot", stringAppendIdAndName(depot,true));
        storeJson.put("phyLocation",stringAppendIdAndName(phyLocation,true));
        storeJson.put("locations",stringAppendIdAndName(locationList,true));
        storeJson.put("site", stringAppendIdAndName(site,true));
        storeJson.put("groupDept", stringAppendIdAndName(groupDept,true));
        storeJson.put("shippingAddress", stringAppendIdAndName(shippingAddress,true));
        storeJson.put("mainShippingAddress", stringAppendIdAndName(mainShippingAddress,true));
        storeJson.put("DcDistributionRange", dcDistributionRanges);

        return storeJson;
    }

    /**
     * 拼接编码和名称
     * @param jsonArray
     * @param idFlag
     * @return
     */
    public String stringAppendIdAndName(JSONArray jsonArray,Boolean idFlag){
        StringBuffer sf = new StringBuffer();
        jsonArray.stream().forEach(o ->{
            JSONObject json = (JSONObject)o;
            if (idFlag)sf.append('['+json.getString("ID")+']');
            if (json.getString("ID")==null) {
                return;
            }
            sf.append(json.getString("NAME")+";");
        });
        return sf.toString();
    }

    public Store update(SimpleRequest request) {
        Store store = request.getO(Store.class);
        setCity(store);
        String id = request.get("id");
        List<Store> stores = storeRepository.findAll(JpaDsl.toCriteriaByEq("id", id));

        Integer versions = request.get("version");
        if (stores.size()!=1) throw new RuntimeException("门店信息【" + id + "】在系统中不存在或有错误数据。");
        Store oldStore = stores.get(0);
        if (store.getVersion() != versions) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        store.setBranchEntry(oldStore.getBranchEntry());
        if(store.getLogo()!=null){
            if(store.getLogo().split("\\},\\{").length>5){
                throw new RuntimeException("最多只能保存5张照片");
            }
        }
        if (store.getOrigin() != null) {
            JSONObject data = new JSONObject();
            data.put("DDID", store.getOrigin());
            if (store.isFckbj()) {
                data.put("FCKBJ", 1);
            } else {
                data.put("FCKBJ", 0);
            }
        }
//        store.setStoreAreaInquiries(oldStore.getStoreAreaInquiries());
        Store saveAndFlush = storeRepository.saveAndFlush(store);
        saveAndFlush.setStoreInfo(store.getStoreInfo());
        return saveAndFlush;
    }

    public Store delete(SimpleRequest request) throws Exception  {
        String id = request.get("id");
        Integer versions = request.get("version");

        List<Store> stores = storeRepository.findAll(JpaDsl.toCriteriaByEq("id", id));
        if (stores.size()!=1) throw new RuntimeException("门店信息【" + id + "】在系统中不存在或有错误数据。");
        Store store = stores.get(0);
        if (store.getVersion() != versions) throw new RuntimeException("记录已更新或已删除，请重新提交！");

        return storeRepository.saveAndFlush(store);
    }

    public Store findOne(String id) {
        return storeRepository.findOne(id);
    }

    public Store findStoreByDept(Dept dept){
        List<Store> list = storeRepository.findAll(JpaDsl.toCriteriaByEq("dept.id",dept.getId()));
        if(list.size() != 1) throw new RuntimeException("请检查主数据：门店类型");
        return list.stream().findFirst().get();
    }

    /**
     * 封库判断
     * @param location
     */
    public void judgeFCKBJ(Location location) {
        if (location.getDepot().getDept() == null) {
            return;
        }
        Store store = storeRepository.findOne(location.getDepot().getDept().getId());
        if (store != null && store.isFckbj() == true) {
            throw new RuntimeException(location.getName() + " 已封库，无法调货");
        }
    }

    public boolean judgeFCKBJFlag(Location location) {
        if (location.getDepot().getDept() == null) {
            return false;
        }
        Store store = storeRepository.findOne(location.getDepot().getDept().getId());
        if (store != null && store.isFckbj() == true) {
            return true;
        }
        return false;
    }


    /**
     * 根部dept找商圈
     * @param dept
     * @return
     */
    public BusinessCircle findBusinessCircleByDept(Dept dept){
        Store store = storeRepository.findByDept(dept) ;
        if(store == null) throw new RuntimeException("门店信息不存在，连联系行政部门定义");
        if(store.getBusinessCircle() == null) throw new RuntimeException("商圈信息不存在，请联系行政部门定义");
        return store.getBusinessCircle();
    }
}
